package org.ailuoli.guard.api.controller;


import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ailuoli.guard.domain.entity.Account;
import org.ailuoli.guard.domain.entity.ConfirmPwd;
import org.ailuoli.guard.domain.entity.PastConfirmPwd;
import org.ailuoli.guard.domain.entity.PastPwd;
import org.ailuoli.guard.domain.enums.DeleteEnum;
import org.ailuoli.guard.domain.enums.StatusEnum;
import org.ailuoli.guard.domain.service.AccountService;
import org.ailuoli.guard.domain.service.ConfirmPwdService;
import org.ailuoli.guard.domain.service.PastConfirmPwdService;
import org.ailuoli.guard.domain.service.PastPwdService;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.tools.bedrock.http.resp.RR;
import org.tools.bedrock.http.resp.v2.R;
import org.tools.bedrock.util.BaseUtils;
import org.tools.bedrock.util.Lists;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.List;

/**
 * @author sander
 * @date 2025/01/30
 **/
@Slf4j
@RestController
@RequestMapping("account")
@RequiredArgsConstructor
public class AccountController {

    private final AccountService accountService;
    private final PastPwdService pastPwdService;
    private final ConfirmPwdService confirmPwdService;
    private final PastConfirmPwdService pastConfirmPwdService;

    @PostMapping
    public RR list() {
        return R.ok(accountService.lambdaQuery()
                .eq(Account::getDeleted, DeleteEnum.FALSE.value())
                .list());
    }

    @PostMapping("add")
    public RR add(@RequestBody Account account) throws Exception {
        return R.ok(accountService.saveAccount(account));
    }

    @PutMapping
    public RR edit(@RequestBody Account account) throws Exception {
        Assert.notNull(account.getId(), "id不能为空");
        // 不允许修改密码
        account.setPassword(null);
        return R.ok(accountService.saveOrUpdateAccount(account));
    }

    @PutMapping("pwd")
    public RR editPwd(@RequestBody Account account) {
        Assert.notNull(account.getId(), "id不能为空");

        Account oAccount = accountService.getById(account.getId());
        List<PastPwd> pastPwdList = pastPwdService.lambdaQuery()
                .eq(PastPwd::getAccountId, account.getId())
                .orderByDesc(PastPwd::getCreatedAt)
                // 3个月内的历史密码
                .gt(PastPwd::getCreatedAt, Timestamp.valueOf(LocalDateTime.now().minusMonths(3)))
                .list();

        if (Lists.isNotEmpty(pastPwdList)) {
            for (PastPwd pastPwd : pastPwdList) {
                if (BaseUtils.isNotEmpty(pastPwd.getPassword()) &&
                        pastPwd.getPassword().equals(account.getPassword())) {
                    return R.fail("新密码不能与近3个月历史密码相同");
                }
            }
        }

        if (BaseUtils.isNotEmpty(oAccount.getPassword()) &&
                oAccount.getPassword().equals(account.getPassword())) {
            return R.fail("新密码不能与历上一次密码相同");
        }

        accountService.lambdaUpdate()
                .set(Account::getPassword, account.getPassword())
                .eq(Account::getId, account.getId())
                .update();

        PastPwd pastPwd = new PastPwd();
        pastPwd.setAccountId(account.getId());
        pastPwd.setPassword(oAccount.getPassword());
        pastPwd.setCreatedAt(Timestamp.valueOf(LocalDateTime.now()));
        pastPwdService.save(pastPwd);

        return R.ok();
    }

    @PostMapping("pastPwd")
    public RR pastPwdList(@RequestParam("accountId") Long accountId) {
        Assert.notNull(accountId, "accountId不能为空");
        return R.ok(pastPwdService.lambdaQuery()
                .eq(PastPwd::getAccountId, accountId)
                .orderByDesc(PastPwd::getCreatedAt)
                .list());
    }

    @DeleteMapping
    public RR delete(@RequestParam("id") Long id) {
        Assert.notNull(id, "id不能为空");
        return R.ok(accountService.lambdaUpdate()
                .set(Account::getDeleted, DeleteEnum.TRUE.value())
                .eq(Account::getId, id)
                .update());
    }

    @PutMapping("status")
    public RR status(@RequestParam("id") Long id, @RequestParam("status") String status) {
        Assert.notNull(id, "id不能为空");
        Assert.notNull(status, "status不能为空");

        StatusEnum statusEnum = StatusEnum.of(status);
        if (StatusEnum.ERROR.equals(statusEnum)) {
            return R.fail(String.format("status: %s 不合法", statusEnum.value()));
        }

        return R.ok(accountService.lambdaUpdate()
                .set(Account::getStatus, statusEnum.value())
                .eq(Account::getId, id)
                .update());
    }

    @PostMapping("confirmPwd")
    public RR confirmPwdList(@RequestParam("accountId") Long accountId) {
        Assert.notNull(accountId, "accountId不能为空");
        return R.ok(confirmPwdService.lambdaQuery()
                .eq(ConfirmPwd::getAccountId, accountId)
                .one());
    }

    @PostMapping("confirmPwd/add")
    public RR confirmPwdAdd(@RequestBody ConfirmPwd confirmPwd) {
        Assert.notNull(confirmPwd.getAccountId(), "accountId不能为空");
        Assert.notNull(confirmPwd.getCPassword(), "confirmPwd不能为空");

        ConfirmPwd oConfirmPwd = confirmPwdService.lambdaQuery()
                .eq(ConfirmPwd::getAccountId, confirmPwd.getAccountId())
                .one();

        if (BaseUtils.isNotEmpty(oConfirmPwd)) {
            return R.fail("已存在确认密码");
        }

        return R.ok(confirmPwdService.save(confirmPwd));
    }

    @PutMapping("confirmPwd")
    public RR confirmPwdEdit(@RequestBody ConfirmPwd confirmPwd) {
        Assert.notNull(confirmPwd.getId(), "id不能为空");
        Assert.notNull(confirmPwd.getAccountId(), "accountId不能为空");
        Assert.notNull(confirmPwd.getCPassword(), "confirmPwd不能为空");

        ConfirmPwd oConfirmPwd = confirmPwdService.lambdaQuery()
                .eq(ConfirmPwd::getId, confirmPwd.getId())
                .one();

        if (BaseUtils.isEmpty(oConfirmPwd)) {
            return R.fail("确认密码不存在");
        }

        if (oConfirmPwd.getCPassword().equals(confirmPwd.getCPassword())) {
            return R.fail("新二级密码不能与上一次二级密码相同");
        }

        List<PastConfirmPwd> oPastConfirmPwdList = pastConfirmPwdService.lambdaQuery()
                .eq(PastConfirmPwd::getAccountId, confirmPwd.getAccountId())
                .orderByDesc(PastConfirmPwd::getCreatedAt)
                // 3个月内的历史确认密码
                .gt(PastConfirmPwd::getCreatedAt, Timestamp.valueOf(LocalDateTime.now().minusMonths(3)))
                .list();

        if (Lists.isNotEmpty(oPastConfirmPwdList)) {
            for (PastConfirmPwd oPastConfirmPwd : oPastConfirmPwdList) {
                if (confirmPwd.getCPassword().equals(oPastConfirmPwd.getCPassword())) {
                    return R.fail("新确认密码不能与近3个月历史确认密码相同");
                }
            }
        }

        confirmPwdService.saveOrUpdate(confirmPwd);

        PastConfirmPwd pastConfirmPwd = new PastConfirmPwd();
        pastConfirmPwd.setAccountId(confirmPwd.getAccountId());
        pastConfirmPwd.setCPassword(oConfirmPwd.getCPassword());
        return R.ok(pastConfirmPwdService.save(pastConfirmPwd));
    }

    @PostMapping("pastConfirmPwd")
    public RR pastConfirmPwdList(@RequestParam("accountId") Long accountId) {
        Assert.notNull(accountId, "accountId不能为空");
        return R.ok(pastConfirmPwdService.lambdaQuery()
                .eq(PastConfirmPwd::getAccountId, accountId)
                .orderByDesc(PastConfirmPwd::getCreatedAt)
                .list());
    }

}
